package cn.nexttec.noteplayer.ui.VideoFile

import android.content.ServiceConnection
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.AdapterView.OnItemSelectedListener
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import cn.nexttec.noteplayer.R
import cn.nexttec.noteplayer.common.Preference
import cn.nexttec.noteplayer.common.TAG
import cn.nexttec.noteplayer.common.debug
import cn.nexttec.noteplayer.common.gson
import cn.nexttec.noteplayer.databinding.FragmentFilesBinding
import cn.nexttec.noteplayer.events.FileScanDoneEvent
import cn.nexttec.noteplayer.models.SortMethod
import cn.nexttec.noteplayer.models.VideoFileInfo
import cn.nexttec.noteplayer.models.VideoFileInfo.Companion.sort
import cn.nexttec.noteplayer.service.FileScanService
import cn.nexttec.noteplayer.ui.activities.PlayerActivity
import cn.nexttec.noteplayer.ui.activities.SearchActivity
import cn.nexttec.noteplayer.ui.adapters.VideoFileAdapter
import cn.nexttec.noteplayer.ui.widget.PopupDialog
import dagger.hilt.android.AndroidEntryPoint
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import javax.inject.Inject

/**
 * Fragment that demonstrates a responsive layout pattern where the format of the content
 * transforms depending on the size of the screen. Specifically this Fragment shows items in
 * the [RecyclerView] using LinearLayoutManager in a small screen
 * and shows items using GridLayoutManager in a large screen.
 */
@AndroidEntryPoint
class FileFragment : Fragment() {
    private var canClick = true
    private lateinit var adapter: VideoFileAdapter
    private val handler = Handler(Looper.getMainLooper())

    @Inject
    lateinit var preference: Preference
    private val viewModel: FileViewModel by activityViewModels()
    private var _binding: FragmentFilesBinding? = null
    private var isShowingMenu = false
    private var conn: ServiceConnection? = null
    private var scanService: FileScanService? = null
    private var sortMethod = SortMethod.FILENAME_ASC
    private var sortMethodIndex = 0
    private var reverse = false

    // This property is only valid between onCreateView and
    // onDestroyView.
    private val binding get() = _binding!!
    private var lastScrollPosition: Int = 0
    private var isTopLevel: Boolean = true
    var topFiles: List<VideoFileInfo>? = null
    private var currentFiles:List<VideoFileInfo>? = null

    private val backCallback = object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            if (!isTopLevel) {
                returnTopLevel()
            } else {
                // 不拦截，传递返回事件
                isEnabled = false
                requireActivity().onBackPressedDispatcher.onBackPressed()
            }
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
//        viewModel = ViewModelProvider(this).get(FileViewModel::class.java)
        _binding = FragmentFilesBinding.inflate(inflater, container, false)
        val root: View = binding.root


        handleBackPressed()


        if (EventBus.getDefault().isRegistered(this).not()) {
            EventBus.getDefault().register(this)
        }

        val recyclerView = binding.recyclerView
        adapter = VideoFileAdapter()

        binding.llSearch?.setOnClickListener {
            SearchActivity.startActivity(requireContext(),0)
        }

        binding.searchBox.setOnClickListener {
            SearchActivity.startActivity(requireContext(),0)
        }

        binding.btnBack.setOnClickListener {
            returnTopLevel()
        }

        binding.btnClose?.setOnClickListener {
            binding.llSort?.visibility = View.GONE
        }

        binding.spSortOrder?.onItemSelectedListener = object :OnItemSelectedListener{
            override fun onItemSelected(
                parent: AdapterView<*>?,
                view: View?,
                position: Int,
                id: Long
            ) {
                reverse = position == 1
                updateFiles()
            }

            override fun onNothingSelected(parent: AdapterView<*>?) {

            }

        }

        binding.spSortMethod?.onItemSelectedListener = object :OnItemSelectedListener{
            override fun onItemSelected(
                parent: AdapterView<*>?,
                view: View?,
                position: Int,
                id: Long
            ) {
                sortMethodIndex = position
                updateFiles()
            }

            override fun onNothingSelected(parent: AdapterView<*>?) {
            }

        }


        binding.btnMore?.setOnClickListener {
            val menu = "menu"
            if (PopupDialog.isShowing(menu)) {
                PopupDialog.dismiss(menu)
                return@setOnClickListener
            } else {
                PopupDialog.showFileMenu(it) { tag ->
                    if (!canClick) {
                        return@showFileMenu
                    }
                    canClick = false
                    handler.postDelayed({ canClick = true }, 1000L)
                    when (tag) {
                        "scan" -> {
                            binding.progressbar!!.visibility = View.VISIBLE
                            if (scanService == null) {
                                conn = FileScanService.bind(requireContext()) {
                                    scanService = it
                                    it.scanVideoFiles()
                                }
                            } else {
                                adapter.clear()
                                scanService!!.scanVideoFiles()
                            }
                            preference.isScanfinished = false
                        }

                        "private" -> {

                        }

                        "sort" -> {
                            TAG debug "llSort visible: ${binding.llSort!!.visibility == View.VISIBLE}"
                            if (binding.llSort!!.visibility == View.GONE) {
                                binding.llSort!!.visibility = View.VISIBLE
                            } else {
                                binding.llSort!!.visibility = View.GONE
                            }
                        }
                    }

                }
            }
        }


        adapter.onItemClick = {
            TAG debug "click ${it.gson()}"
            if (it.isDirectory) {
                lastScrollPosition =
                    (binding.recyclerView.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
                viewModel.loadDirectory(it)
                binding.btnIcon!!.visibility = View.GONE
                binding.btnBack.visibility = View.VISIBLE
                isTopLevel = false
            } else {
                PlayerActivity.start(requireActivity(), it)
            }
        }
        recyclerView.adapter = adapter

        viewModel.topFiles.observe(requireActivity()) {
            this.topFiles = it.sort(sortMethod)
            this.currentFiles = this.topFiles
            adapter.setVideoFiles(this.currentFiles?: emptyList(), false)
        }

        viewModel.files.observe(requireActivity()) {
            currentFiles = it.sort(sortMethod)
            adapter.setVideoFiles(this.currentFiles?: emptyList(), false)
        }
        viewModel.loadFiles()
        return root
    }

    private fun updateFiles() {
        sortMethod = when (sortMethodIndex) {
            0 -> if (reverse) SortMethod.FILE_SIZE_DESC else SortMethod.FILENAME_ASC
            1 -> if (reverse) SortMethod.FILE_SIZE_DESC else SortMethod.FILE_SIZE_ASC
            else -> if (reverse) SortMethod.FILE_TIME_DESC else SortMethod.FILE_TIME_ASC
        }
        currentFiles = currentFiles?.sort(sortMethod)?: emptyList()
        adapter.setVideoFiles(currentFiles!!, false)
    }

    private fun returnTopLevel() {
        isTopLevel = true
        adapter.setVideoFiles(topFiles!!, false)
        binding.recyclerView.scrollToPosition(lastScrollPosition)
        binding.btnIcon!!.visibility = View.VISIBLE
        binding.btnBack.visibility = View.GONE
    }

    private fun handleBackPressed() {
        requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, backCallback)
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onFileScanCompleted(e: FileScanDoneEvent) {

        if (!preference.isScanfinished) {
            preference.isScanfinished = true
            viewModel.loadFiles()
        }
        binding.progressbar!!.visibility = View.GONE
    }

    override fun onDestroyView() {
        super.onDestroyView()
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this)
        }
        conn?.let {
            requireContext().unbindService(it)
        }
        _binding = null
    }


}